#include <time.h>
#include <unistd.h>
#include <sys/reboot.h>
#include <errno.h>

#include "charge.h"
#include "charge_user.h"
#include "charge_os.h"
#include "qlcloud_client.h"

enum _ERR_CODE
{
	CAN_COMM_ERR1  = 400, //can通信故障—心跳中断
	CAN_COMM_ERR2  =401,//  can通信异常—遥测中断
	CAN_COMM_ERR3  =402  ,//can通信异常—遥信中断
	MT_COMM_ERR=403,//  电表通信故障
	CARD_COMM_ERR=404,//  读卡器异常
	CHA_OVERBACK_PF01=405 ,// 控制器充电指令回应超时
	CHA_OVERBACK_PE11=406,//  控制器充电完成指令超时
	GUN_DISCONN=407,// 枪未连接
    CHA_START_FIN =408 ,// 桩正在充电
    TCU_NOT_READY=409 ,//匹配阶段未完成  桩未准备好
    COMB_DISABLE=410,//  本桩不支持共充或枪编号错误
    CHA_OVERBACK_PF03=411,//  控制器充电停止指令回应超时
    CHA_OVERBACK_PF13=412,//  控制器充电停止完成指令超时
    CHARGE_STOP_UNEXP=413,//  充电意外停止Unexpected  充电过程中，控制器自行返回待机，或等待充电过程中，控制器摇信返回充电完成，但是没有返回启动完成失败帧
    COMB_SET_FAIL=414,// 共充设置失败
    OTHER_ERR=416,// 鉴权失败
    NET_CLOSED=417,//网络中断
    INVALID_MODLE=418,//无效计费模型
    MT_DATA_ERR=419,//电表数据异常
};
user_pile_t g_user_pile;
user_gun_t  g_user_gun[CHARGE_GUN_CNT];
user_bms_t  g_user_bms[CHARGE_GUN_CNT];
user_lock_t g_user_lock[CHARGE_GUN_CNT];

u8 g_update_bill_flag[CHARGE_GUN_CNT] = {0};

// 启动充电信息QL_updateYC
extern start_mx g_startInfo[CHARGE_GUN_CNT];

// 充电参数
extern Charge_Arg g_chargepara_ql[CHARGE_GUN_CNT];

// 停止充电信息
extern end_mx g_stopInfo[CHARGE_GUN_CNT];

// 电表实时数据
extern MeterDataReal g_realmtData[CHARGE_GUN_CNT+1];

// 读取的最后充电功率
extern u32 last_kWh[];
extern MeterData_ql g_mtData[CHARGE_GUN_CNT];

// 设备充电停电操作结果
extern int update_operate_result[8];

// 设备操作结果标志及原因
extern u16  charge_operate_result[8][2];

void thread_sleep(unsigned long usec)
{
    struct timeval tv;
    tv.tv_sec = usec / 1000000;
    tv.tv_usec = usec % 1000000;

    int err;
    do {
        err = select(0, NULL, NULL, NULL, &tv);
    } while(err < 0 && errno == EINTR);
}

//更新充电枪充电实时数据
void user_update_gun_data(uint8_t gun_id)
{

}

void set_update_bill_flag(u8 gun_id, u8 val)
{
	g_update_bill_flag[gun_id - 1] = val;
}

void user_update_gun_data_by_yc(uint8_t gun_id,  void *p_data)
{
    union u_out_mx* p_yc = (union u_out_mx*)p_data;
    user_gun_t *p_gun = &g_user_gun[gun_id - 1];
    
    if (gt_para_from_main.type == ql_gun_type_dc)
    {
    	// 在上报状态时，数据必须有效
		p_gun->temperature = convert_temperature( p_yc->dc.MX[7] &0xFF);//枪线温度
		p_gun->voltage     = p_yc->dc.MX[0];//输出电压
		p_gun->current     = p_yc->dc.MX[1];//输出电流
		p_gun->battery_max_temp = convert_temperature( p_yc->dc.MX[4] &0xFF);//电池组最高温度
		p_gun->battery_min_temp = convert_temperature( p_yc->dc.MX[3] &0xFF);//电池组最低温度

		if (((charge_get_gun_state(gun_id) != GUN_STATE_CHARGING) || ((p_yc->dc.MX[2] &0xFF) > 0)) && (g_update_bill_flag[gun_id - 1] == 0))
		{
			p_gun->soc              = p_yc->dc.MX[2] &0xFF; // SOC
			p_gun->current_charge_kwh = g_realmtData[gun_id - 1].kWh[0]*100;//当前电表度数，单位:0.0001度
		}
		p_gun->remain_charge_time =  p_yc->dc.MX[14];//(p_yc->dc.MX[14] + 50)/ 100;//估算剩余充电时间

		p_gun->lose_charge_kwh    = 0; //计损总度数，单位:0.0001度

        log_debug("YC[%d] V:%d, I:%d, time:%d kwh:%d\r\n", gun_id, p_yc->dc.MX[0], p_yc->dc.MX[1], p_yc->dc.MX[14], g_realmtData[gun_id - 1].kWh[0]*100);
    }
    else if (gt_para_from_main.type == ql_gun_type_ac)
    {
        // 交流无数据，无法更新 
    }
}



//更新BMS参数配置阶段数据0x50
void user_update_bms_config(uint8_t gun_id)
{

}

//更新BMS充电阶段数据0x51
void user_update_bms_charging(uint8_t gun_id)
{

}


void user_update_bms_charging_by_start_MX(uint8_t gun_id)
{
    start_mx *p_mx    = &g_startInfo[gun_id - 1];
    user_bms_t *p_bms = &g_user_bms[gun_id - 1];
    char brm_battery_supplier[BRM_BATT_SUP_LEN + 1] = "aab0";
    uint8_t brm_battery_produce_date[BRM_BATT_DATE_LEN] = {0xE4, 0x07, 0x0B, 0x1E}; //2020-11-30
    uint8_t brm_bms_software_version[BRM_BMS_SOFT_VER_LEN] = {0x01, 0x1E, 0x0B, 0xE4, 0x07, 0xFF, 0xFF, 0xFF}; //01.30.11.2020.FFFFFF
    
    memcpy(p_bms->brm_bms_connect_version, &p_mx->dc.MX4[0], BRM_VERSION_LEN);//BRM-BMS通讯协议版本号
    p_bms->brm_battery_type = p_mx->dc.MX7;//电池类型
    p_bms->brm_battery_rated_capacity = p_mx->dc.MX14;//整车动力蓄电池系统额定容量
    p_bms->brm_battery_volt = p_mx->dc.MX12;//整车动力蓄电池系统额定总电压
    memcpy(p_bms->brm_battery_supplier, brm_battery_supplier, BRM_BATT_SUP_LEN);//BRM电池生产厂商
    p_bms->brm_battery_no = 0;//电池组序号
    memcpy(p_bms->brm_battery_produce_date, brm_battery_produce_date, BRM_BATT_DATE_LEN);//BRM-电池组生产日期：第1,2字节表示年,3字节表示月,4字节表示日
    p_bms->brm_battery_charge_count = 0;// 电池组充电次数
    p_bms->brm_battery_property_id = 0;// 电池组产权标识
    memcpy(p_bms->brm_bms_software_version, brm_bms_software_version, BRM_BMS_SOFT_VER_LEN);// BMS软件版本号
    memcpy(p_bms->brm_vin, p_mx->dc.MX21, BRM_VIN_LEN);//车辆识别码vin
    p_bms->bcp_max_voltage = p_mx->dc.MX10;//单体动力蓄电池最高允许充电电压
    p_bms->bcp_max_current = p_mx->dc.MX11;//最高允许充电电流
    p_bms->bcp_max_power   = p_mx->dc.MX15;//动力蓄电池标称总能量
    p_bms->bcp_total_voltage = p_mx->dc.MX15;//最高允许充电总电压
    p_bms->bcp_max_temperature = p_mx->dc.MX9;//最高允许温度
    p_bms->bcp_battery_soc = p_mx->dc.MX16;//整车动力蓄电池荷电状态(soc)
    p_bms->bcp_battery_soc_current_voltage = p_mx->dc.MX13;//整车动力蓄电池当前电池电压
    p_bms->bro_bms_is_ready = 0x00;//BRO-BMS是否充电准备好
    p_bms->cro_is_ready     = 0xff;//CRO-充电机是否充电准备好
}

//更新BMS充电结束阶段数据0x52 0x53 0x54
void user_update_bms_stop(uint8_t gun_id)
{
    
}

void user_update_bms_charging_by_end_MX(uint8_t gun_id)
{
    end_mx* p_mx = &g_stopInfo[gun_id - 1];
    user_bms_t *p_bms = &g_user_bms[gun_id - 1];

    p_bms->bsd_stop_soc = p_mx->dc.MX6;//BSD-终止荷电状态soc 
    p_bms->bsd_battery_low_voltage = p_mx->dc.MX7;//BSD-动力蓄电池单体最低电压
    p_bms->bsd_battery_high_voltage = p_mx->dc.MX8;//BSD-动力蓄电池单体最高电压
    p_bms->bsd_battery_low_temperature = p_mx->dc.MX9;//BSD-动力蓄电池最低温度
    p_bms->bsd_battery_high_temperature = p_mx->dc.MX10;//BSD-动力蓄电池最高温度
    p_bms->bem_error_spn2560_00 = p_mx->dc.MX11 & 0x00FF;//BEM-接收SPN2560=0x00的充电桩辨识报文超时
    p_bms->bem_error_spn2560_aa = p_mx->dc.MX12 & 0x00FF;//BEM-接收SPN2560=0xaa的充电桩辨识报文超时
    p_bms->bem_error_time_sync  = p_mx->dc.MX13 & 0x00FF;//BEM-接收充电桩的时间同步和最大输出能力报文超时
    p_bms->bem_error_ready_to_charge = p_mx->dc.MX14 & 0x00FF;//BEM-接收充电桩完成充电准备报文超时
    p_bms->bem_error_receive_status = p_mx->dc.MX15 & 0x00FF;//BEM-接收充电桩充电状态报文超时
    p_bms->bem_error_receive_stop = p_mx->dc.MX16 & 0x00FF;//BEM-接收充电桩终止充电报文超时
    p_bms->bem_error_receive_statistics = p_mx->dc.MX17 & 0x00FF;//BEM-接收充电桩充电统计报文超时
    p_bms->bem_error_other = p_mx->dc.MX18[0] & 0x00FF;//BEM-其他
    p_bms->cst_stop_reason = p_mx->dc.MX26[0];//CST - 充电机中止原因
    p_bms->cst_fault_reason = p_mx->dc.MX26[1];//CST - 充电机中止原因
    p_bms->cst_error_reason = p_mx->dc.MX26[2];//CST - 中止充电错误原因
    p_bms->bst_stop_reason = p_mx->dc.MX26[3];//BST - 充电机中止原因
    p_bms->bst_fault_reason = p_mx->dc.MX26[4];//BST - 中止充电故障原因
    p_bms->bst_error_reason = p_mx->dc.MX26[5];//BST - 中止充电错误原因
}

//更新地锁状态信息
void user_update_lock(uint8_t lock_id, LOCK_STATE_t lock_state)
{
    uint8_t lock_index = lock_id - 1;

    g_user_lock[lock_index].state = lock_state;
    g_user_lock[lock_index].battery = 50 + lock_index;
}
//20210619 add
u16 start_charge_result(u16 ret)
{
    const u16 charge_result_to_err_code[][2] =
    {
        {CAN_COMM_ERR1, DEV_ERR_3032},  // can通信故障—心跳中断
        {CAN_COMM_ERR2, DEV_ERR_3032},  // can通信故障—心跳中断
        {CAN_COMM_ERR3, DEV_ERR_3032},  // can通信故障—心跳中断
        {MT_COMM_ERR,   DEV_ERR_300D},  // 电表通信错误
        {GUN_DISCONN,   DEV_ERR_301B},  // 充电连接故障
        {CHA_START_FIN, DEV_ERR_301D},  // 充电连接故障
        {TCU_NOT_READY, DEV_ERR_301D}   // 桩未能准备好
    };
    int num = sizeof(charge_result_to_err_code) / 4;
    int i;
    u16 err_code = DEV_ERR_301D;

    for (i = 0; i < num; i++)
    {
        if (charge_result_to_err_code[i][0] == ret)
        {
            err_code = charge_result_to_err_code[i][1];
            break;
        }
    }

    return err_code;
}//add end
//操作硬件开启充电
uint16_t user_hardware_start_charge(uint8_t gun_id)
{
    uint16_t err = DEV_ERR_301A; //0   20210619 modify by cz
    int ret = 0;
    Charge_Arg*  p_arg = &g_chargepara_ql[gun_id - 1];
    int cnt = 0;
	t_operate_reason op_reason;
    cmdlist  cmd;
	
    //请在此操作硬件充电枪开启充电
    //成功返回0，失败返回错误码
    //err = 0xb047;
    p_arg->guntab = gun_id - 1;
    err = (uint16_t)gt_para_from_main.startCharge(gun_id - 1, (void*)p_arg);
    if (err == 0)
	{
		update_operate_result[gun_id - 1] = 0;
		for (cnt = 0; cnt < 1200; cnt++)
		{
			if (update_operate_result[gun_id - 1] == 1)
			{
				if (charge_operate_result[gun_id - 1][0] == 0)
				{
					err = 0;
				}
				else
				{
					err = charge_operate_result[gun_id - 1][1];
				}
				break;
			}
			// 线程休眠100ms
			thread_sleep(100000);
		}

		if (cnt >= 1200)
		{
			err =  DEV_ERR_301A; //0xb037 20210619 add by cz
		}
	}
    //20210619  add by cz
    else
    {
    	err = start_charge_result(err);
    }
    log_debug("user_cb_start_charging gun:%d result:%d \r\n", gun_id, err);

	if (err > 0)
	{
		op_reason.gun_id = gun_id - 1;
		if ((err >= 0x5000) && (err < 0x6000))
	    {
			op_reason.reason = 6;	// BMS故障
		}
		else
		{
			op_reason.reason = 5;	// 桩故障
		}
		op_reason.detail_code = err;
		
		// 设置故障信息 
		cmd.cmdtype = SET_STOP_DETAIL_REASON;
		cmd.body	= (void*)&op_reason;
		gt_para_from_main.cmd_fun(&cmd);
	}

    return err;
}

// 根据停止码获取停止原因 
u8 get_stop_reason_by_fee(uint16_t stop_code)
{
	//粤易充		   1.本地刷卡终止，2.远程终止充电，3充满自动停止，4余额不足，5充电桩故障，6 BMS故障，7、急停按钮停止，
				//8.验证码停止，9.停电结束，10.按电量满足结束，11.按金额满足结束，12.按时间满足结束，13.拔枪结束，
	const uint16_t map_stop_info[][2] = {
	    {1, CHARGE_STOP_CARD},  // 刷卡结束 
	    {2, CHARGE_STOP_APP},   // APP远程结束 
	    {3, CHARGE_STOP_FULL},  // 充满自行停止
	    {4, CHARGE_STOP_BALANCE},   // 余额不足
	    {8, CHARGE_STOP_SCREEN},    // 触控屏手动停止 
	    {2, CHARGE_STOP_PLATFROM},  // 平台终止充电
	    {11, CHARGE_STOP_MONEY}, // 达到充电金额 
	    {10, CHARGE_STOP_ELEC},  // 电量满足
	    {12, CHARGE_STOP_TIME},  // 时间满足 
	    {13, CHARGE_STOP_PULL_GUN}, // 把枪结束 
	    {7,  DEV_ERR_3003}, // 紧急按钮 
    };
    int info_num = sizeof(map_stop_info) / 4;
    int i;
    u8  stop_reason = 2;

    for (i = 0; i < info_num; i++)
    {
        if (stop_code == map_stop_info[i][1])
        {
            stop_reason = (map_stop_info[i][0] & 0x00FF);
            break;
        }
    }

    if (i >= info_num)
    {
        if (((stop_code >= 0x3000) && (stop_code < 0x5000))
            || ((stop_code >= 0x6000) && (stop_code < 0x7000)))
        {
            stop_reason = 5;
        }
        else if ((stop_code >= 0x5000) && (stop_code < 0x6000))
        {
            stop_reason = 6;
        }
    }
    
    return stop_reason;
}

//操作硬件停止充电
uint16_t user_hardware_stop_charge(uint8_t gun_id)
{
    uint16_t err = 0;
    uint16_t stop_reason = 0;
    int cnt = 0;
    fee_t fee;
	t_operate_reason op_reason = {0};
    cmdlist  cmd;
	
    //请在此操作硬件充电枪停止充电
    //成功返回0，失败返回错误码
    op_reason.gun_id = gun_id - 1;
    // 获取当前枪费用信息
    get_gun_fee(gun_id - 1, &fee);
    stop_reason = get_stop_reason_by_fee(fee.stop_code) ;
	op_reason.reason = stop_reason;
    
    update_operate_result[gun_id - 1] = 0;
    err = (uint16_t)gt_para_from_main.stopCharge(gun_id - 1, (void*)&stop_reason);
    if (err == 0)
	{
		for (cnt = 0; cnt < 1200; cnt++)
		{
			if (update_operate_result[gun_id - 1] == 1)
			{
				if (charge_operate_result[gun_id - 1][0] == 0)
				{
					err = 0;
				}
				else
				{
					err = charge_operate_result[gun_id - 1][1];
				}
				break;
			}
			// 线程休眠100ms 
			thread_sleep(100000);
		}

		if (cnt >= 1200)
		{
			err = DEV_ERR_3032;
		}
	}

    log_debug("user_cb_stop_charging gun:%d result:%d \r\n", gun_id, err);
	
	if (err > 0)
	{
        if ((err >= 0x3000) && (err < 0x5000))
        {
            // 桩故障，等待修复 
			if (err == DEV_ERR_3003)
			{
				op_reason.reason = 7;
			}
			else
		    {
				op_reason.reason = 5;
		    }
        }
        else if ((err >= 0x5000) && (err < 0x6000))
        {
			op_reason.reason = 6;
        }
		else if ((err >= 0x1000) && (err < 0x2000))
		{
			op_reason.reason = get_stop_reason_by_fee(err);
		}
		op_reason.detail_code = err;
		
		// 设置故障信息 
		cmd.cmdtype = SET_STOP_DETAIL_REASON;
		cmd.body	= (void*)&op_reason;
	}
	
	gt_para_from_main.cmd_fun(&cmd);

    return err;
}

void user_cb_start_charging(uint8_t gun_id, uint16_t *err)
{
    log_debug("user_cb_start_charging gun:%d\r\n", gun_id);
    //调用硬件开启充电
    if (0 == (*err = user_hardware_start_charge(gun_id)))
    {
        user_update_gun_data(gun_id);
        user_update_bms_charging(gun_id);
    }
}

void user_cb_stop_charging(uint8_t gun_id, uint16_t *err)
{
    log_debug("user_cb_stop_charging gun:%d\r\n", gun_id);
    //调用硬件停止充电
    if (0 == (*err = user_hardware_stop_charge(gun_id)))
    {
        user_update_bms_stop(gun_id);
    }
}

#if SUPPORT_LOCK
//0x91
void user_cb_lock_switch(uint8_t lock_id, uint8_t _switch, uint8_t *err)
{
    //请在此函数中操作硬件控制地锁
    gt_para_from_main.unlock_func(lock_id - 1, _switch);
    log_debug("user_cb_lock_switch gun:%d, switch:%d\r\n", lock_id, _switch);
    *err = 0;
}
#endif

//0xb0
void user_cb_set_time(uint32_t timestamp, os_time_t *time)
{
    struct tm tptr;
    struct timeval tv;
    
    //请在此函数中设置时间
    log_debug("user_cb_set_time ts:%d, tm:%04d-%02d-%02d#%02d:%02d:%02d\r\n", timestamp,
        time->year, time->mon, time->day, time->hour, time->min, time->sec);

    tptr.tm_year = time->year - 1900;
    tptr.tm_mon = time->mon - 1;
    tptr.tm_mday = time->day;
    tptr.tm_hour = time->hour;
    tptr.tm_min = time->min;
    tptr.tm_sec = time->sec;
    
    tv.tv_sec = mktime(&tptr);
    tv.tv_usec = 0;
    settimeofday(&tv, NULL);
}

int32_t user_cb_card_auth(const uint8_t card_id[8], uint32_t *balance)
{
    //需要对卡号进行权限验证，验证通过须将卡余额赋值
    log_debug("刷卡鉴权,卡号[%s]鉴权成功\r\n", card_id);
    *balance = 9999;//如支持离线充电，设置一个很大的余额，充满为止
    
    return CARD_AUTH_OK;
}

void user_cb_connected(uint32_t timestamp)
{
    cmdlist  cmd;
    
    //连接云端成功
    log_debug("user_cb_connected:%d\r\n", timestamp);
    
    cmd.cmdtype = RENEW_NET_FLAG;
    cmd.body    = (void*)1;
    
    gt_para_from_main.cmd_fun(&cmd);
}

void user_cb_dissconnected(uint32_t timestamp)
{
    cmdlist  cmd;
    
    //连接断开
    log_debug("user_cb_dissconnected:%d\r\n", timestamp);
    cmd.cmdtype = RENEW_NET_FLAG;
    cmd.body    = (void*)0;
    
    gt_para_from_main.cmd_fun(&cmd);
}

//0x03
void user_cb_reboot_pile(uint8_t cmd, uint16_t *err)
{
    //3秒钟后重启充电桩
    log_debug("user_cb_reboot_pile :%d\r\n", cmd);
    *err = 0;

    sleep(3);
    sync();
    
    reboot(RB_AUTOBOOT);
}

//0x05
void user_cb_power_alloc(uint8_t gun_id, uint32_t max_out_power, uint16_t *err)
{
    //充电枪功率分配
    log_debug("user_cb_power_alloc gun_id:%d, max_out_power:%d\r\n", gun_id, max_out_power);
    *err = 0;
    if (gt_para_from_main.adjust_charge_pw)
    	gt_para_from_main.adjust_charge_pw(gun_id - 1, 1, max_out_power);
}

//0x09
void user_cb_qr_code()
{
    //充电枪收到二维码
    uint8_t i = 0;
    u8  cmd_type[] = {SET_1ST_QRCODE, SET_2ND_QRCODE};
    cmdlist cmd;
    
    for (i = 0; i < CHARGE_GUN_CNT; i++)
    {
        log_debug("收到枪:[%d],的二维码:%s\r\n", i + 1, g_user_gun[i].qr_code);
        
        cmd.cmdtype = cmd_type[i];
        cmd.body    = (void*)g_user_gun[i].qr_code;
        
        if (gt_para_from_main.cmd_fun)
        	gt_para_from_main.cmd_fun(&cmd);
    }
}

void save_ql_fee( price_t * p_ql_fee)
{
    int i;
    u8 type;
    ql_fee_config *p_fee = &gt_para_from_main.fee_config;
    cmdlist  cmd;

    for (i = 0; i < 48; i++)
    {
        type  = p_ql_fee->period[i] & 0x03;
        p_fee->charge_fee[i] = p_ql_fee->price_elec[type];
        type  = (p_ql_fee->period[i] & 0x0C) >> 2;
        p_fee->service_fee[i] = p_ql_fee->price_service[type];
    }
    
    // 保存配置 
    cmd.cmdtype = SAVE_FEE_CFG;
    cmd.body    = (void*)&gt_para_from_main;
    gt_para_from_main.cmd_fun(&cmd);
}


//0x07
void user_cb_set_params(uint16_t *err)
{
    //设置充电桩工作参数
    uint8_t i = 0;
    log_debug("收到设置充电桩工作参数指令\r\n");
    log_debug("p8:%d, p9:%d, p10:%d, p11:%d, p12H:%d, p12L:%d, p13H:%d, p13L:%d, p14H:%d, p14L:%d, \
    p15:%d, p16:%d, p17:%d, p18:%d, p19:%d, p20:%d, p21:%d, p22:%d, p23:%d, p24:%d, p25H:%d, p25L:%d, \
    p26:%d, p27:%d, p28:%d, p29:%d, p30:%d, p31:%d \n", \
        g_user_pile.param_group.param_8, g_user_pile.param_group.param_9, g_user_pile.param_group.param_10, g_user_pile.param_group.param_11, \
        g_user_pile.param_group.param_12.param_1, g_user_pile.param_group.param_12.param_2, g_user_pile.param_group.param_13.param_1, g_user_pile.param_group.param_13.param_2, \
        g_user_pile.param_group.param_14.param_1, g_user_pile.param_group.param_14.param_2, g_user_pile.param_group.param_15, g_user_pile.param_group.param_16, \
        g_user_pile.param_group.param_17, g_user_pile.param_group.param_18, g_user_pile.param_group.param_19, g_user_pile.param_group.param_20, \
        g_user_pile.param_group.param_21, g_user_pile.param_group.param_22, g_user_pile.param_group.param_23, g_user_pile.param_group.param_24, \
        g_user_pile.param_group.param_25.param_1, g_user_pile.param_group.param_25.param_2, g_user_pile.param_group.param_26, g_user_pile.param_group.param_27, \
        g_user_pile.param_group.param_28, g_user_pile.param_group.param_29, g_user_pile.param_group.param_30, g_user_pile.param_group.param_31);
    
    *err = 0;
}

//0x36
void user_cb_gun_release(uint8_t gun_id, uint8_t *cmd_response_status)
{
    //设置充电桩工作参数
    uint8_t i = 0;
    log_debug("收到设置充电桩解除卡枪指令  枪编号 %d\n", gun_id);

    *cmd_response_status = 0;
    gt_para_from_main.unlock_func(gun_id - 1, 1);
}

static const char *p_file_name = "/usr/local/sanway/dbTest/ql-data";
int32_t user_write_data(const void *data, uint32_t data_len)
{
    int rc = 0;
    FILE *file;

    file = fopen(p_file_name, "rb+");
    if (file == NULL)
    {
        file = fopen(p_file_name, "wb+");
        if (file == NULL)
        {
            log_error("save open err\r\n");
            return -1;
        }
    }

    rc = fwrite(data, sizeof(unsigned char), data_len, file);
    if (rc == data_len)
    {
        rc = 0;
    }
    else
    {
        rc = -1;
    }

    fclose(file);

    return rc;
}

int32_t user_read_data(void *data, uint32_t data_len)
{
    int rc = 0;
    FILE *file;

    file = fopen(p_file_name, "rb+");
    if (file == NULL)
    {
        file = fopen(p_file_name, "wb+");
        if (file == NULL)
        {
            log_error("load open err\r\n");
            return -1;
        }
    }

    rc = fread(data, sizeof(unsigned char), data_len, file);
    //"rc == 0" means the first to read the file
    if (rc <= data_len || rc == 0)
    {
        rc = 0;
    }
    else
    {
        rc = -1;
    }

    fclose(file);

    return rc;
}

int32_t user_create_download_file(char *file_name)
{
    FILE *file;

    //第一包清空文件
    file = fopen(file_name, "wb+");
    if (file == NULL)
    {
        log_error("save open err\r\n");
        return -1;
    }

    fclose(file);
}

int32_t user_write_download_file_data(char *file_name, uint32_t offset, void *data, uint16_t data_len)
{
    int rc = 0;
    FILE *file;

    /* 先判断文件是否存在 */
    file = fopen(file_name, "rb+");
    if (file == NULL)
    {
        return -1;
    }
    else
    {
        fclose(file);
    }

    file = fopen(file_name, "ab+");
    if (file == NULL)
    {
        return -1;
    }

    rc = fwrite(data, sizeof(unsigned char), data_len, file);
    if (rc == data_len)
    {
        rc = 0;
    }
    else
    {
        rc = -1;
    }

    fclose(file);

    return rc;
}

int32_t user_download_file_done(char *file_name, uint8_t state)
{
    cmdlist  cmd;

    cmd.cmdtype = UPDATA_FILES;
    cmd.body    = (void*)1;

    gt_para_from_main.cmd_fun(&cmd);
    
    return 0;
}
